<?php
namespace Common\Controller;

use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Parser;
use Think\Exception;

class ApibaseController
{
    const TOKEN_KEY_NAME = 'uid';      //jwt token key string 关键值


    /**
     * @var string json 文档说明;如果为空就不显示
     */
    protected $json_doc;

    /**
     * 架构函数
     * @access public
     */


    public function __construct()
    {
//        if (!IS_POST) {
//            return $this->error('只接受post请求!!!');
//        }
    }

    /**
     * 检查操作频率
     * @param int $duration 距离最后一次操作的时长
     */
    protected function check_last_action($duration)
    {

        $action = MODULE_NAME . "-" . CONTROLLER_NAME . "-" . ACTION_NAME;
        $time = time();

        $session_last_action = session('last_action');
        if (!empty($session_last_action['action']) && $action == $session_last_action['action']) {
            $mduration = $time - $session_last_action['time'];
            if ($duration > $mduration) {
                $this->error("您的操作太过频繁，请稍后再试~~~");
            } else {
                session('last_action.time', $time);
            }
        } else {
            session('last_action.action', $action);
            session('last_action.time', $time);
        }
    }


    /**
     * @param string $key 需要加密的键(key)
     * @param string $value 需要加密的值
     * @param string $salt 加密的salt建议不要修改
     * @return \Lcobucci\JWT\Token 访问jwt token 字符串
     */
    protected function createTokenStringByUserId($uid)
    {
        $token_live_time = C('TOKEN_LIVE_TIME', null, 60 * 60 * 24 * 30);//30天过期
        $salt = 'world_flower_rocks';
        $expires_in = time() + $token_live_time;
        $host = $_SERVER['HTTP_HOST'];
        $signer = new Sha256();
        $token = (new Builder())
            ->set(self::TOKEN_KEY_NAME, $uid)// Configures a new claim, called "uid"
            ->setExpiration($expires_in)
            ->setIssuer($host)
            ->sign($signer, $salt)// creates a signature using "testing" as key
            ->getToken(); // Retrieves the generated token
        $token = (string)$token;
        return compact('token', 'expires_in','uid'); // The string representation of the object is a JWT string (pretty easy, right?)
    }

    /**
     * 根据发送的token参数得到uid, 获取登陆的用户信息
     */
    protected function parseTokenUID($tokenString = null)
    {
        $tokenString = empty($tokenString)? I('token') : $tokenString;

        if(empty($tokenString)){
            $this->error('token不能为空');
        }

        try {
            $token = (new Parser())->parse($tokenString); // Parses from a string
            if (!APP_DEBUG) {
                //验证token来源是否合法
                $host = $_SERVER['HTTP_HOST'];
                $issuer = $token->getClaim('iss');
                if ($issuer !== $host) {
                    return $this->error('跨域token!');
                }

                //验证token失效时间
                $expires_time = $token->getClaim('exp');
                $now_time = time();
                if ($now_time > $expires_time) {
                    return $this->error('token已经过期请重新登录!');
                }
            }
            //返回uid;
            $uid = $token->getClaim(self::TOKEN_KEY_NAME);

            return $uid;
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
    }

    protected function jsonReturn($data = null, $description = 'success', $status = 1)
    {
        header('Content-Type:application/json; charset=utf-8');
        header('Status:200 OK');
        header('HTTP/1.1 200 OK');

        $jsonArray['status'] = $status;
        $jsonArray['data'] = $data;

        $jsonArray['msg'] = $description;//json 说明
        if (APP_DEBUG) {
            $jsonArray['server_recieved_parameters'] = I('param.');//参数
            if (!empty(I('token'))) {
                $jsonArray['server_recieved_parameters']['token_parse_uid'] = $this->parseTokenUID();
            }
            //API api 接口里面直接返回文档
            if (!empty($this->json_doc)) {
                $this->json_doc = array_merge(['字段' => '说明'], $this->json_doc);
                $jsonArray['json_doc'] = $this->json_doc;
            }
        }

        exit(json_encode($jsonArray, JSON_UNESCAPED_UNICODE));
    }

    /**
     * @param null $data Array
     * @param string $description 描述
     * @param int $status 状态
     * 接口数字字符创进行升级 去掉数字之后的引号
     */
    protected function jsonReturn2 ($data = null, $description = 'success', $status = 1)
    {
        header('Content-Type:application/json; charset=utf-8');
        header('Status:200 OK');
        header('HTTP/1.1 200 OK');
        $jsonArray['status'] = $status;
        $jsonArray['data'] = $data;

        $jsonArray['msg'] = $description;//json 说明
        $ipADD = get_client_ip();
        if ($ipADD == '0.0.0.0') {//如果是localhost
            $jsonArray['debug_parameter'] = I('param.');//参数
            if (!empty(I('token'))) {
                $jsonArray['debug_parameter']['token_uid'] = $this->parseTokenUID();
            }
            //API api 接口里面直接返回文档
            if (!empty($this->json_doc)) {
                $this->json_doc = array_merge(['字段' => '说明'], $this->json_doc);
                $jsonArray['json_doc'] = $this->json_doc;
            }
        }
        exit(json_encode($jsonArray, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK));
    }

    protected function error($message = 'error')
    {
        $this->jsonReturn2(null, $message, 0);
    }

    protected function success($message = 'success')
    {
        $this->jsonReturn2(null, $message, 1);
    }


    /**
     *  分页辅助方法
     */
    protected function pageHelper($model, $where = null, $order = null, $field = null)
    {

        $page_size = I('page_size', 16,'intval');
        $current_page = I('current_page', 1,'intval');

        $total_count = $model->where($where)->Count();
        $total_page = ceil($total_count / $page_size);
        $list = $model->where($where)->field($field)->order($order)->page($current_page, $page_size)->select();
        $pageArray = compact('total_page', 'current_page', 'page_size', 'list');
        return $pageArray;

    }

    /**
     * 添加用户金币记录, 修改用户金币总金额
     * 1:金币抽奖 2:金币奖品 3:积分兑换 4:新手任务 5:每日签到 6:金币退换
     */
    protected function addCoinRecord($uid, $type, $title, $description, $coin)
    {
        $user_coin_data = [
            'uid' => $uid,
            'title' => $title,
            'description' => "$description",
            'coin' => $coin,
            'ip' => get_client_ip(),
            'coin_type' => intval($type),
            'create_time' => date('Y-m-d H:i:s'),
            'update_time' => date('Y-m-d H:i:s'),
        ];

        $res = D('UsersCoinRecord')->add($user_coin_data);
        if (!$res) {
            return 0;
        }
        //计算用户金币数量
        $user_coin_count = D('UsersCoinRecord')->where(compact('uid'))->sum('coin');
        D('Users')->where(['id' => $uid])->save(['coin' => $user_coin_count]);

        return $res;
    }


}